import Event from './Event.js'
import Food from './Food.js'
import Map from './Map.js'
import Snake from './Snake.js'

// 游戏控制器
class Game extends Event{
  constructor(el, rect, toControl = null, toOver = null, toWin = null) {
    super();
    this.el = el;
    this.rect = rect;
    this.toControl = toControl;
    // this.toGrade = toGrade;
    this.toOver = toOver;
    this.toWin = toWin;
    this.map = new Map(el, rect);
    this.food = new Food(this.map.cells, this.map.rows);
    this.snake = new Snake();
    this.keyDown = this.keyDown.bind(this);
    
    this.map.setData(this.snake.data);
    this.createFood();
    this.map.setData(this.food.data);

    this.map.render();

    this.timer = null;
    this.interval = 200;
    this.grade = 0;

    this.control();
  }

  // 开始游戏
  start() {
    this.move();
  }

  // 暂停游戏
  stop() {
    clearInterval(this.timer);
  }

  // 控制移动
  move() {
    this.stop();
    this.timer = setInterval(() => {
      this.snake.move();
      this.map.clearData();
      if (this.isEatFood()) {
        this.snake.eatFood();
        this.food.create();
        this.grade++;
        // this.changeGrade(this.grade); 
        this.dispatch('changeGrade', this.grade);
        this.interval *= .9;
        this.stop();
        this.start();
        if (this.grade >= 25) {
          this.over(1);
        }
      }
      if (this.isOver()) {
        this.over(0);
        return;
      }
      this.map.setData(this.snake.data);
      this.map.setData(this.food.data);
      this.map.setData(this.food.data);
      this.map.render();
    }, this.interval);
  }

  createFood() {
    if (this.map.include(this.food.data)) {
      this.food.create();
    }
  }

  // 分数改变
  // changeGrade(grade) {
  //   this.toGrade && this.toGrade(grade);
  // }

  // 是否吃到食物
  isEatFood() {
    return (this.snake.data[0].x === this.food.data.x) && (this.snake.data[0].y === this.food.data.y);
  }

  // 是否结束
  isOver() {
    // 蛇出了地图
    if (this.snake.data[0].x < 0
      || this.snake.data[0].x >= this.map.cells
      || this.snake.data[0].y < 0
      || this.snake.data[0].y >= this.map.rows) {
      return true;
    }
    // 判断撞到自己
    for (let i = 1; i < this.snake.data.length; i++){
      if (this.snake.data[0].x == this.snake.data[i].x
        && this.snake.data[0].y == this.snake.data[i].y) {
        return true;
      }
    }

    return false;
  }

  // 结束
  // status 0 中间停止 挂了
  // status 1 胜利
  over(status = 0) {
    if (status === 0) {
      this.toOver && this.toOver();
    } else {
      this.toWin && this.toWin();
    }
    this.stop();
  }

  keyDown({ keyCode }) {
    switch (keyCode) {
      case 37:
        this.snake.changeDir('left');
        break;
      case 38:
        this.snake.changeDir('top');
        break;
      case 39:
        this.snake.changeDir('right');
        break;
      case 40:
        this.snake.changeDir('bottom');
        break;
    }
  }
  // 控制器
  control() {
    if (this.toControl) {
      this.toControl();
      return;
    }
    
    window.addEventListener('keydown', this.keyDown)
  }

  addControl(fn) {
    fn.call(this);
    window.removeEventListener('keydown', this.keyDown)
  }
}

export default Game;